/**
 * Copyright (C) 2009, 2010 SC 4ViewSoft SRL
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cc.mango.android.chart;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.text.DecimalFormat;

import org.achartengine.chart.AbstractChart;
import org.achartengine.chart.ScatterChart;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.DefaultRenderer;
import org.achartengine.renderer.SimpleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer.Orientation;
import org.achartengine.util.MathHelper;

import cc.mango.android.dto.StkDaily;
import cc.mango.android.dto.StkIntraday;
import cc.mango.common.FinalKey;
import cc.mango.common.StringUtils;
import cc.telecomdigital.tdstock.Framework.UniqueItem.TDStockLog;
import cc.telecomdigital.tdstock.activity.chart.NvChart;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.view.MotionEvent;
import static cc.mango.android.chartutil.ChartCommons.*;

/**
 * The XY chart rendering class.
 */
public class CandlestickChart extends UpXYChart
{

	/**
	 * 
	 */
	private static final long	serialVersionUID	= -4475119821510406109L;

	protected List				dataList;

	/*  // 涨的颜色
	  protected final int riseColor = 0xff00ff00;
	  
	  // 跌的颜色
	  protected final int fallColor = 0xffff0000;*/

	protected float[]			lowAndHighPoints;

	protected float[]			openAndClosePoints;

	protected float			lowHighLineWidth	= 1;

	protected float			rectWidth			= 6;

	/**
	 * Builds a new XY chart instance.
	 * 
	 * @param dataset the multiple series dataset
	 * @param renderer the multiple series renderer
	 */

	public CandlestickChart(XYMultipleSeriesDataset dataset,
			XYMultipleSeriesRenderer renderer, NvChart nvChart, List dataList)
	{
		// TODO Auto-generated constructor stub
		super(dataset, renderer, nvChart);

		this.dataList = dataList;

	}

	/**
	   * The graphical representation of the XY chart.
	   * 
	   * @param canvas the canvas to paint to
	   * @param x the top left x value of the view to draw to
	   * @param y the top left y value of the view to draw to
	   * @param width the width of the view to draw to
	   * @param height the height of the view to draw to
	   */
	@Override
	public void draw(Canvas canvas, int x, int y, int width, int height)
	{

		Paint paint = new Paint();
		paint.setAntiAlias(mRenderer.isAntialiasing());

		initSize(width, height);

		int left = x + leftWidth;
		int top = y + topHeight;
		int right = x + width - rightWidth;
		int bottom = y + height - bottomHeight;

		if (screenR == null)
		{
			screenR = new Rect();
		}
		screenR.set(left, top, right, bottom);

		drawTopBackground(mRenderer, canvas, left, y, right, top, paint);

		drawBackground(mRenderer, canvas, left, top, right - left, bottom
				- top, paint);//background

		drawBackgroundDottedLine(canvas, left, top, right - left, bottom
				- top, new Paint());

		if (paint.getTypeface() == null
				|| !paint.getTypeface().toString().equals(
						mRenderer.getTextTypefaceName())
				|| paint.getTypeface().getStyle() != mRenderer
						.getTextTypefaceStyle())
		{
			paint.setTypeface(Typeface.create(mRenderer
					.getTextTypefaceName(), mRenderer
					.getTextTypefaceStyle()));
		}
		Orientation or = mRenderer.getOrientation();

		double minX = mRenderer.getXAxisMin();
		double maxX = mRenderer.getXAxisMax();
		double minY = mRenderer.getYAxisMin();
		double maxY = mRenderer.getYAxisMax();
		boolean isMinXSet = mRenderer.isMinXSet();
		boolean isMaxXSet = mRenderer.isMaxXSet();
		boolean isMinYSet = mRenderer.isMinYSet();
		boolean isMaxYSet = mRenderer.isMaxYSet();

		int sLength = mDataset.getSeriesCount();
		String[] titles = new String[sLength];
		for (int i = 0; i < sLength; i++)
		{
			XYSeries series = mDataset.getSeriesAt(i);
			titles[i] = series.getTitle();
			if (series.getItemCount() == 0)
			{
				continue;
			}
			if (!isMinXSet)
			{
				double minimumX = series.getMinX();
				minX = Math.min(minX, minimumX);
				calcRange[0] = minX;
			}
			if (!isMaxXSet)
			{
				double maximumX = series.getMaxX();
				maxX = Math.max(maxX, maximumX);
				calcRange[1] = maxX;
			}

			double minimumY = series.getMinY();
			/*  if(!isEqual(minY, 0)){
				  minY = Math.min(minY, (float) minimumY);
				  calcRange[2] = minY;
			  }
			  else{
				  minY = minimumY;
				  calcRange[2] = minimumY;
			  }*/

			minY = getMinY(minY, minimumY);

			double maximumY = series.getMaxY();
			maxY = Math.max(maxY, (float) maximumY);
			calcRange[3] = maxY;

		}

		if (maxX - minX != 0)
		{
			//      xPixelsPerUnit = (right - left) / (maxX - minX);
			int count = this.mDataset.getSeriesAt(0).getItemCount();
			if (count == 0)
			{
				return;
			}
			xPixelsPerUnit = 1.0f * (right - left) / (count - 1);
		}
		/* if (maxY - minY != 0) {
		   yPixelsPerUnit = (float) ((bottom - top) / (maxY - minY));
		 	
		 }*/

		if (!isEqual(maxY, minY))
		{

			yPixelsPerUnit = (float) ((bottom - top) / (maxY - minY));

		}

		boolean hasValues = true;//by zhengan

		/////////////by zhengan   调整了绘线的位置，调到了绘制坐标的后面
		//draw label and grid
		boolean showLabels = mRenderer.isShowLabels() && hasValues;
		boolean showGrid = mRenderer.isShowGrid();
		if (showLabels || showGrid)
		{

			if (showLabels)
			{
				paint.setColor(mRenderer.getLabelsColor());
				paint.setTextSize(mRenderer.getLabelsTextSize());
				paint.setTextAlign(Align.CENTER);//by zhengan origin

				drawXLabels(canvas, paint);

				drawYLabels(canvas, paint);

			}

		}

		//如果是一周的情况，在没有触摸的时候没有竖线
		if (getIsWeekChart() && !getIsTouching())
		{
			TDStockLog.d("Print_Info", "isWeekChart verticlaline");
			drawWeekChartVerticalLine(canvas, screenR.top, screenR.bottom,
					new Paint());
		}

		if (getIsTouching())
		{
			//	    	float xLocation = (float) ((mDataset.getSeriesAt(0).getX(NvChart.index)-calcRange[0]) * xPixelsPerUnit);

			float xLocation = getXLocation(getIndex());

			TDStockLog.d("Print_Info", "xLocation:" + xLocation);

			drawVerticalLine(canvas, xLocation, top, bottom);

			drawTopBm(canvas, getBmX(xLocation), y, bmWidth, topHeight,
					getYValue(getIndex()));

		}

		initPoints(left, bottom, minY, dataList);

		drawCandlestickSeries(canvas, paint);//绘制烛状图

	}

	/**
	* The graphical representation of a series.
	* 
	* @param canvas the canvas to paint to
	* @param paint the paint to be used for drawing
	* @param points the array of points to be used for drawing the series
	* @param seriesRenderer the series renderer
	* @param yAxisValue the minimum value of the y axis
	* @param seriesIndex the index of the series currently being drawn
	*/
	public void drawSeries(Canvas canvas, Paint paint, float[] points,
			SimpleSeriesRenderer seriesRenderer, float yAxisValue,
			int seriesIndex)
	{
		int length = points.length;
		XYSeriesRenderer renderer = (XYSeriesRenderer) seriesRenderer;
		float lineWidth = paint.getStrokeWidth();
		paint.setStrokeWidth(renderer.getLineWidth());
		if (renderer.isFillBelowLine())
		{
			paint.setColor(renderer.getFillBelowLineColor());
			int pLength = points.length;
			float[] fillPoints = new float[pLength + 4];
			System.arraycopy(points, 0, fillPoints, 0, length);
			fillPoints[0] = points[0] + 1;
			fillPoints[length] = fillPoints[length - 2];
			fillPoints[length + 1] = yAxisValue;
			fillPoints[length + 2] = fillPoints[0];
			fillPoints[length + 3] = fillPoints[length + 1];
			paint.setStyle(Style.FILL);
			drawPath(canvas, fillPoints, paint, true);
		}
		paint.setColor(seriesRenderer.getColor());
		paint.setStyle(Style.STROKE);
		drawPath(canvas, points, paint, false);
		paint.setStrokeWidth(lineWidth);
	}

	public void initPoints(float left, float bottom, double minY, List list)
	{

		if (lowAndHighPoints != null && lowAndHighPoints.length != 0
				&& openAndClosePoints != null
				&& openAndClosePoints.length != 0)
		{

			return;
		}

		int size = list.size();

		/*	rectWidth = 1.0f * screenR.width() / size * 2 / 3;
			
			if(rectWidth > 5){
				
				rectWidth = 5;
			}*/

		rectWidth = 1.0f * screenR.width() / size * 2 / 3;

		String dateType = nvChart.getDateType();

		if (FinalKey.INTRADAY_DATETYPE_TODAY.equals(dateType)
				|| FinalKey.DAILY_DATETYPE_YEAR.equals(dateType)
				|| FinalKey.DAILY_DATETYPE_2YEARS.equals(dateType))
		{

			rectWidth = 1.0f * screenR.width() / 500 * 2 / 3;

		}
		/*else if(FinalKey.INTRADAY_DATETYPE_WEEK.equals(dateType)||
				FinalKey.DAILY_DATETYPE_6MONTHS.equals(dateType)){
		
			
		}else if(FinalKey.DAILY_DATETYPE_6MONTHS.equals(dateType)){
			
		}
		else if(FinalKey.DAILY_DATETYPE_MONTH.equals(dateType)){
			
		}*/

		if (rectWidth > 5)
		{

			rectWidth = 5;
		}

		Object data = list.get(0);

		if (data instanceof StkIntraday)
		{

			//			initInstradayPoints(list);
			getIntradayCandlestickPoints(left, bottom, minY, list);

		}
		else if (data instanceof StkDaily)
		{

			//			initDailyPoints(list);

			getDailyCandlestickPoints(left, bottom, minY, list);
		}

	}

	public void getDailyCandlestickPoints(float left, float bottom,
			double minY, List<StkDaily> list)
	{

		/*if(lowAndHighPoints !=null && lowAndHighPoints.length !=0 &&
				openAndClosePoints !=null && openAndClosePoints.length !=0 ){
			
			return;
		}
		*/
		int size = list.size();

		StkDaily data;

		lowAndHighPoints = new float[size * 4];
		openAndClosePoints = new float[size * 4];

		for (int i = 0; i < size; i++)
		{

			data = list.get(i);

			lowAndHighPoints[i * 4] = (float) (left + xPixelsPerUnit * i);
			lowAndHighPoints[i * 4 + 1] = (float) (bottom - yPixelsPerUnit
					* (data.getLow() - minY));
			lowAndHighPoints[i * 4 + 2] = (float) (left + xPixelsPerUnit * i);
			lowAndHighPoints[i * 4 + 3] = (float) (bottom - yPixelsPerUnit
					* (data.getHigh() - minY));

			//当开盘和收盘价格没有差距时
			if (isEqual(data.getOpen(), data.getClose()))
			{

				openAndClosePoints[i * 4] = (float) (left + xPixelsPerUnit
						* i - 1.0f * rectWidth / 2);
				openAndClosePoints[i * 4 + 1] = (float) (bottom - yPixelsPerUnit
						* (data.getOpen() - minY));
				openAndClosePoints[i * 4 + 2] = (float) (left
						+ xPixelsPerUnit * i + 1.0f * rectWidth / 2);
				openAndClosePoints[i * 4 + 3] = (float) (bottom
						- yPixelsPerUnit * (data.getClose() - minY) - 2);

			}
			else
			{

				openAndClosePoints[i * 4] = (float) (left + xPixelsPerUnit
						* i - 1.0f * rectWidth / 2);
				openAndClosePoints[i * 4 + 1] = (float) (bottom - yPixelsPerUnit
						* (data.getOpen() - minY));
				openAndClosePoints[i * 4 + 2] = (float) (left
						+ xPixelsPerUnit * i + 1.0f * rectWidth / 2);
				openAndClosePoints[i * 4 + 3] = (float) (bottom - yPixelsPerUnit
						* (data.getClose() - minY));

			}

		}

	}

	public void getIntradayCandlestickPoints(float left, float bottom,
			double minY, List<StkIntraday> list)
	{

		/*if(lowAndHighPoints !=null && lowAndHighPoints.length !=0 &&
				openAndClosePoints !=null && openAndClosePoints.length !=0 ){
			
			return;
		}

		int size = list.size();
		
		rectWidth = 1.0f * screenR.width() / size * 2 / 3;
		
		if(rectWidth > 6){
			
			rectWidth = 6;
		}*/

		int size = list.size();

		StkIntraday data;

		lowAndHighPoints = new float[size * 4];
		openAndClosePoints = new float[size * 4];

		for (int i = 0; i < size; i++)
		{

			data = list.get(i);

			lowAndHighPoints[i * 4] = (float) (left + xPixelsPerUnit * i);
			lowAndHighPoints[i * 4 + 1] = (float) (bottom - yPixelsPerUnit
					* (data.getDaylow() - minY));
			lowAndHighPoints[i * 4 + 2] = (float) (left + xPixelsPerUnit * i);
			lowAndHighPoints[i * 4 + 3] = (float) (bottom - yPixelsPerUnit
					* (data.getDayhigh() - minY));

			//当开盘和收盘价格没有差距时
			if (isEqual(data.getOpen(), data.getClose()))
			{

				openAndClosePoints[i * 4] = (float) (left + xPixelsPerUnit
						* i)
						- 1.0f * rectWidth / 2;
				openAndClosePoints[i * 4 + 1] = (float) (bottom - yPixelsPerUnit
						* (data.getOpen() - minY));
				openAndClosePoints[i * 4 + 2] = (float) (left + xPixelsPerUnit
						* i)
						+ 1.0f * rectWidth / 2;
				openAndClosePoints[i * 4 + 3] = (float) (bottom
						- yPixelsPerUnit * (data.getClose() - minY) - 2);

			}
			else
			{

				openAndClosePoints[i * 4] = (float) (left + xPixelsPerUnit
						* i)
						- 1.0f * rectWidth / 2;
				openAndClosePoints[i * 4 + 1] = (float) (bottom - yPixelsPerUnit
						* (data.getOpen() - minY));
				openAndClosePoints[i * 4 + 2] = (float) (left + xPixelsPerUnit
						* i)
						+ 1.0f * rectWidth / 2;
				openAndClosePoints[i * 4 + 3] = (float) (bottom - yPixelsPerUnit
						* (data.getClose() - minY));
			}

		}

	}

	protected void drawCandlestickSeries(Canvas canvas, Paint paint)
	{

		int size = dataList.size();

		paint = new Paint();
		paint.setAntiAlias(true);
		paint.setColor(Color.WHITE);
		paint.setStyle(Style.FILL);
		paint.setStrokeWidth(lowHighLineWidth);
		//绘制最低和最高值
		for (int i = 0; i < size; i++)
		{

			canvas.drawLine(lowAndHighPoints[i * 4],
					lowAndHighPoints[i * 4 + 1],
					lowAndHighPoints[i * 4 + 2],
					lowAndHighPoints[i * 4 + 3], paint);

		}

		//绘制开盘和最收盘值
		for (int i = 0; i < size; i++)
		{

			if (openAndClosePoints[i * 4 + 1] > openAndClosePoints[i * 4 + 3])
			{

				paint.setColor(CANDLE_RISE_Color);

				canvas.drawRect(openAndClosePoints[i * 4],
						openAndClosePoints[i * 4 + 1],
						openAndClosePoints[i * 4 + 2],
						openAndClosePoints[i * 4 + 3], paint);

			}
			else
			{

				paint.setColor(CANDLE_FALL_Color);

				canvas.drawRect(openAndClosePoints[i * 4],
						openAndClosePoints[i * 4 + 1],
						openAndClosePoints[i * 4 + 2],
						openAndClosePoints[i * 4 + 3], paint);

			}

		}

	}

	/**
	 * Draws the chart background.
	 * 
	 * @param renderer the chart renderer
	 * @param canvas the canvas to paint to
	 * @param x the top left x value of the view to draw to
	 * @param y the top left y value of the view to draw to
	 * @param width the width of the view to draw to
	 * @param height the height of the view to draw to
	 * @param paint the paint used for drawing
	 */
	protected void drawBackground(DefaultRenderer renderer, Canvas canvas,
			int x, int y, int width, int height, Paint paint)
	{
		if (renderer.isApplyBackgroundColor())
		{
			paint.setColor(renderer.getBackgroundColor());
			paint.setStyle(Style.FILL);
			canvas
					.drawRect(x - 2, y, x + width + 2f, y + height + 1f,
							paint);
		}
	}

	/*
	 * 
	 * *Draws the  background above chart
	 * @see cc.mango.android.chart.UpXYChart#drawTopBackground(org.achartengine.renderer.DefaultRenderer, android.graphics.Canvas, int, int, int, int, android.graphics.Paint)
	 */

	protected void drawTopBackground(DefaultRenderer renderer, Canvas canvas,
			int left, int top, int right, int bottom, Paint paint)
	{
		if (renderer.isApplyBackgroundColor())
		{
			paint.setColor(UP_CHART_TOP_REGINE_COLOR);
			paint.setStyle(Style.FILL);
			canvas.drawRect(left - 2, top, right + 2, bottom, paint);
		}
	}
}
